#ifndef	__UTF32ENCODIING_H__
#define	__UTF32ENCODIING_H__

namespace BFX
{

// Encodes text into and out of UTF-32.  UTF-32 is a way of writing
// Unicode characters with a single storage unit (32 bits) per character, 
// 
// The UTF-32 byte order mark is simply the Unicode byte order mark
// (0x00FEFF) written in UTF-32 (0x0000FEFF or 0xFFFE0000).  The byte order 
// mark is used mostly to distinguish UTF-32 text from other encodings, and doesn't
// switch the byte orderings.
class REFUTF32Encoding : public REFEncoding
{
public:
	/* 
	words   bits    UTF-32 representation
	-----   ----    ----------------------------------- 
	1       16      00000000 00000000 xxxxxxxx xxxxxxxx
	2       21      00000000 000xxxxx hhhhhhll llllllll
	-----   ----    -----------------------------------

	Surrogate:
	Real Unicode value = (HighSurrogate - 0xD800) * 0x400 + (LowSurrogate - 0xDC00) + 0x10000 
	*/ 
public:
	REFUTF32Encoding(bool bBigEndian = false);
	virtual ~REFUTF32Encoding();

	//
	// Overrides
	//
	virtual int GetMaxByteCount(int nCharCount) const;
	virtual int GetMaxCharCount(int nByteCount) const;
	virtual int GetByteCount(const UCHAR* pChars, int nCount) const;
	virtual int GetBytes(const UCHAR* pChars, int nCharCount, OUT BYTE* pBytes, int nByteCount) const;
	virtual int GetCharCount(const BYTE* pBytes, int nCount, REFDecoder* pDecoder) const;
	virtual int GetChars(const BYTE* pBytes, int nByteCount, OUT UCHAR* pChars, int nCharCount, REFDecoder* pDecoder) const;

	// Returns a Decoder object for this encoding. The returned object can be used to decode a sequence of bytes into a sequence of characters.
	// Contrary to the GetChars family of methods, a Decoder can convert partial sequences of bytes into partial sequences of characters
	// by maintaining the appropriate state between the conversions.
	virtual REFDecoder* GetDecoder() const;

protected:
	UINT32 GetSurrogate(UCHAR cHigh, UCHAR cLow) const
	{
		return (((UINT32)cHigh - 0xD800) * 0x400) + ((UINT32)cLow - 0xDC00) + 0x10000;
	}
	UCHAR GetHighSurrogate(UINT32 iChar) const
	{ 
		return (UCHAR)((iChar - 0x10000) / 0x400 + 0xD800);
	} 
	UCHAR GetLowSurrogate(UINT32 iChar) const
	{ 
		return (UCHAR)((iChar - 0x10000) % 0x400 + 0xDC00);
	}

protected:
	class UTF32Decoder : public REFDecoder
	{
	public:
		UTF32Decoder(const REFEncoding* pEncoding);
		virtual ~UTF32Decoder();
		virtual void Reset();

		// Need a place to store any extra bytes we may have sucked up
		int	m_iChar;
		int	m_nReadByteCount;
	};

protected:
	//
	// Attributes
	//
	bool	m_bBigEndian;
};

}	//	namespace BFX

#endif	//	__UTF32ENCODIING_H__
